/**
 * FileName: AuthFilter Author:   zeroleavebaoyang Date:     2018/8/28 16:36 Description:
 */
package com.shiro.sso.demo.filter;

import com.shiro.sso.demo.config.properties.AuthProperties;
import com.shiro.sso.demo.utils.Constant;
import com.shiro.sso.demo.utils.SsoLoginHelper;
import java.io.IOException;
import java.net.URLEncoder;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.web.filter.authc.AuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;


@Slf4j
public class AuthFilter extends AuthenticationFilter {

    @Autowired
    AuthProperties authProperties;

    public String getCookieName() {
        return authProperties.getCookie().getCookieName();
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response,
            Object mappedValue) {
        // 客户端
        if (StringUtils.equals(authProperties.getType(), Constant.SSO_CLIENT)) {
            HttpServletRequest req = WebUtils.toHttp(request);
            HttpServletResponse res = WebUtils.toHttp(response);
            String cookieSessionId = SsoLoginHelper.getSessionIdByCookie(req);
            Session session = SsoLoginHelper.isLogin(cookieSessionId);
            if (session == null) {
                // remove old cookie
                SsoLoginHelper.removeSessionIdInCookie(req, res);
                // set new cookie
                String paramSessionId = WebUtils.getCleanParam(request, getCookieName());
                if (StringUtils.isNotBlank(paramSessionId)) {
                    session = SsoLoginHelper.isLogin(paramSessionId);
                    if (session != null) {
                        SsoLoginHelper.loginSuccess(res, session);
                        redirectToSelf(req, res);
                        return true;
                    }
                }
            } else {
                // update redis session timeout
                SsoLoginHelper.loginSuccess(res, session);
                return true;
            }
            return false;
        }
        return super.isAccessAllowed(request, response, mappedValue);
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response)
            throws Exception {
        HttpServletRequest req = WebUtils.toHttp(request);
        StringBuffer url = new StringBuffer(authProperties.getLoginUrl());
        if (StringUtils.equals(authProperties.getType(), Constant.SSO_CLIENT)) {
            StringBuffer backurl = req.getRequestURL();//www.a.com:8082/index
            String queryString = req.getQueryString();
            if (StringUtils.isNotBlank(queryString) && !queryString
                    .contains(getCookieName())) {
                backurl.append("?").append(queryString);
            }
            url.append("?").append(Constant.SSO_REDIRECT_URL).append("=")
                    .append(URLEncoder.encode(backurl.toString(), "UTF-8"));
        }
        // 真正的url(http://www.ca.com:8082/login?redirect_url=www.a.com:8082/index)
        WebUtils.toHttp(response).sendRedirect(url.toString());
        return false;
    }


    // 从参数中获取服务端传来的vt后，执行一个到本链接的重定向，将vt写入cookie
    // 重定向后再发来的请求就存在有效vt参数了
    private void redirectToSelf(HttpServletRequest request, HttpServletResponse response) {
        try {
            String PARANAME = getCookieName() + "=";
            StringBuffer location = request.getRequestURL();
            String qstr = request.getQueryString();
            int index = qstr.indexOf(PARANAME);
            //http://www.sys1.com:8081/test/tt?a=2&b=xxx
            if (index > 0) { // 还有其它参数，para1=param1&param2=param2&__vt_param__=xxx是最后一个参数
                qstr = "?" + qstr.substring(0, qstr.indexOf(PARANAME) - 1);
            } else { // 没有其它参数 qstr = __vt_param__=xxx
                qstr = "";
            }
            location.append(qstr);
            response.sendRedirect(location.toString());
        } catch (IOException e) {
            log.error("{}", e);
        }
    }

}

